<script setup lang="ts">
import { computed, reactive, watch } from 'vue';
import { enableStatusOptions } from '@/constants/business';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { fetchEditRole, fetchSaveRole } from '@/service/api';
import { $t } from '@/locales';
import { pick } from '@/utils/common';

defineOptions({
  name: 'RoleOperateModal'
});
interface Props {
  operateType: NaiveUI.TableOperateType;
  rowData?: Api.SystemManage.Role | null;
}
const props = defineProps<Props>();
interface Emits {
  (e: 'submitted'): void;
}
const emit = defineEmits<Emits>();
const visible = defineModel<boolean>('visible', { default: false });
const { formRef, restoreValidation, validate } = useNaiveForm();
const { defaultRequiredRule } = useFormRules();

const title = computed(() => {
  const titles: Record<NaiveUI.TableOperateType, string> = {
    add: $t('page.manage.role.addRole'),
    edit: $t('page.manage.role.editRole')
  };
  return titles[props.operateType];
});

const isEdit = computed(() => props.operateType === 'edit');

type Model = Api.SystemManage.RoleEdit & { id: number | null };
const model: Model = reactive(createDefaultModel());

type RuleKey = Exclude<keyof Model, 'description' | 'level' | 'id'>;
const rules: Record<RuleKey, App.Global.FormRule> = {
  name: defaultRequiredRule,
  code: defaultRequiredRule,
  status: defaultRequiredRule
};
function createDefaultModel(): Model {
  return {
    id: null,
    name: '',
    code: '',
    description: '',
    level: 9999,
    status: '1'
  };
}
async function handleSubmit() {
  await validate();
  const func = isEdit.value ? fetchEditRole : fetchSaveRole;
  // pick 避免出现多余属性。如果先修改，在新增，会包含出Model之外的属性，因此过滤掉Model之外的属性，再提交数据
  const { error, data } = await func(pick(model, Object.keys(createDefaultModel()) as (keyof Model)[]));
  if (!error && data) {
    window.$message?.success($t(isEdit.value ? 'common.updateSuccess' : 'common.addSuccess'));
    closeModal();
    emit('submitted');
  }
}
function closeModal() {
  visible.value = false;
}

function handleInitModel() {
  Object.assign(model, createDefaultModel());
  if (!props.rowData) return;

  if (isEdit.value && props.rowData) {
    Object.assign(model, props.rowData);
  }
}

watch(visible, () => {
  if (visible.value) {
    handleInitModel();
    restoreValidation();
  }
});
</script>

<template>
  <NModal v-model:show="visible" :title="title" preset="card" class="w-720px">
    <NScrollbar>
      <NForm
        ref="formRef"
        :model="model"
        :rules="rules"
        :mask-closable="true"
        label-placement="left"
        label-width="auto"
        require-mark-placement="right-hanging"
      >
        <NFormItem :label="$t('page.manage.role.roleName')" path="name">
          <NInput v-model:value="model.name" :placeholder="$t('page.manage.role.form.roleName')" />
        </NFormItem>
        <NFormItem :label="$t('page.manage.role.roleCode')" path="code">
          <NInput v-model:value="model.code" :placeholder="$t('page.manage.role.form.roleCode')" />
        </NFormItem>
        <NFormItem :label="$t('page.manage.role.roleStatus')" path="status">
          <NRadioGroup v-model:value="model.status">
            <NRadio v-for="item in enableStatusOptions" :key="item.value" :value="item.value" :label="$t(item.label)" />
          </NRadioGroup>
        </NFormItem>
        <NFormItem :label="$t('page.manage.role.roleLevel')" path="level">
          <NInputNumber v-model:value="model.level" :placeholder="$t('page.manage.role.form.roleLevel')" />
        </NFormItem>
        <NFormItem :label="$t('page.manage.role.roleDesc')" path="description">
          <NInput
            v-model:value="model.description"
            :placeholder="$t('page.manage.role.form.roleDesc')"
            type="textarea"
            passively-activated
          />
        </NFormItem>
      </NForm>
    </NScrollbar>
    <template #footer>
      <NSpace justify="end" :size="16">
        <NButton @click="closeModal">{{ $t('common.cancel') }}</NButton>
        <NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
      </NSpace>
    </template>
  </NModal>
</template>

<style scoped></style>
